package co.fitstart.scheduler.service.impl;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.demo2do.core.utils.DateFormatUtils;
import com.demo2do.core.utils.DateUtils;

import co.fitstart.scheduler.Constant;
import co.fitstart.scheduler.persistence.GenericJdbcSupport;
import co.fitstart.scheduler.service.CourseScheduleService;

@Service("courseScheduleService")
public class CourseScheduleServiceImpl implements CourseScheduleService {

    private static final Logger logger = LoggerFactory.getLogger(CourseScheduleServiceImpl.class);

    @Autowired
    private GenericJdbcSupport genericJdbcSupport;

    /*
     * (non-Javadoc)
     * 
     * @see
     * co.fitstart.scheduler.service.CourseScheduleService#expiryCourseSchedule(
     * java.util.Date)
     */
    public void expiryCourseSchedule(Date now) {
        try {

            expiryCourseScheduleTransaction(now);

        } catch (Throwable t) {

            logger.error("expiryCourseScheduleTransaction(): ", t);
        }
    }

    @Transactional
    public void expiryCourseScheduleTransaction(Date now) {

        // 1. 今日逾期年卡课程
        List<Long> yearRoundIdList = listExpiryYearRound(now);

        // 2. 获取失信年卡课程
        if (yearRoundIdList != null && yearRoundIdList.size() > 0) {
            List<Long> list = listMoreThanOneExpiryYearRound(yearRoundIdList);
            if (list != null && list.size() > 0) {
                for (Long yearRoundId : list) {
                    // become dishonesty
                    dishonesty(yearRoundId);
                }
            }
        }
        //在本任务设置课程状态为过期前，先给这个用户添加逾期记录
        Date current = new Date();
        
        //前一天的约课时间
        Date minusDay = DateUtils.addDays(current, -1);
        String thisTime = DateFormatUtils.format(minusDay, "yyyy-MM-dd");
        
        this.addExpire(thisTime);

        // 3. change course schedule to expiry
        Map<String, Object> parameters = new HashMap<String, Object>();
        parameters.put("group", Constant.COURSE_TYPE);
        parameters.put("expiry", Constant.SCHEDULE_STATUS_EXPIRE);
        parameters.put("ready", Constant.SCHEDULE_STATUS_READY);
        parameters.put("today", now);
        
        genericJdbcSupport.executeSQL("UPDATE course_schedule SET schedule_status = :expiry "
                + "WHERE course_type != :group AND occur_date < :today AND schedule_status = :ready "
                + "and is_disabled = 0", parameters);
        
    }

    /*
     * (non-Javadoc)
     * 
     * @see co.fitstart.scheduler.service.CourseScheduleService#
     * toExpiryCourseSchedule(java.util.Date)
     */
    public int toExpiryCourseSchedule(Date now) {
        Map<String, Object> parameters = new HashMap<String, Object>();
        parameters.put("group", Constant.COURSE_TYPE);
        parameters.put("ready", Constant.SCHEDULE_STATUS_READY);
        parameters.put("today", now);
        return genericJdbcSupport.queryForInt("SELECT COUNT(*) FROM course_schedule "
                + "WHERE course_type != :group AND schedule_status = :ready AND occur_date < :today "
                + "and is_disabled = 0", parameters);
    }

    /**
     * list year round list of the expiry schedule
     * 
     * @param now
     * @return
     */
    private List<Long> listExpiryYearRound(Date now) {
        Map<String, Object> parameters = new HashMap<String, Object>();
        parameters.put("year", Constant.COURSE_TYPE_YEAR);
        parameters.put("ready", Constant.SCHEDULE_STATUS_READY);
        parameters.put("today", now);
        return genericJdbcSupport.queryForSingleColumnList(
                "SELECT distinct cr.id " + "FROM course_schedule cs join course_round cr on cs.course_round_id=cr.id "
                        + "WHERE cs.is_disabled=0 and cs.course_type = :year AND cs.schedule_status = :ready AND cs.occur_date < :today",
                parameters, Long.class);
    }

    /**
     * list more than one expiry year round
     * 
     * @param yearRoundIdList
     * @return
     */
    private List<Long> listMoreThanOneExpiryYearRound(List<Long> yearRoundIdList) {
        Map<String, Object> parameters = new HashMap<String, Object>();
        parameters.put("expire", Constant.SCHEDULE_STATUS_EXPIRE);
        parameters.put("ids", yearRoundIdList);
        return genericJdbcSupport.queryForSingleColumnList("select course_round_id from course_schedule"
                + " where schedule_status= :expire and is_disabled=0 and course_round_id in (:ids)"
                + " group by course_round_id having count(*)>0", parameters, Long.class);
    }

    /**
     * dishonesty yearRound
     * 
     * @param yearRoundId
     */
    private void dishonesty(Long yearRoundId) {
        Map<String, Object> parameters = new HashMap<String, Object>();
        parameters.put("id", yearRoundId);

        List<String> values = genericJdbcSupport.queryForSingleColumnList(
                "SELECT value FROM course_round_attr WHERE course_round_id = :id AND name='dishonesty'", parameters,
                String.class);
        if (values == null || values.size() == 0) {
            genericJdbcSupport.executeSQL(
                    "insert into course_round_attr(course_round_id,name,value) values(:id, 'dishonesty', '1')",
                    parameters);
        } else if ("0".equals(values.get(0))) {
            genericJdbcSupport.executeSQL(
                    "UPDATE course_round_attr SET value = '1' WHERE course_round_id = :id AND name = 'dishonesty'",
                    parameters);
        }
    }
    
   
    public void addExpire(String now) {
        Map<String, Object> parameters = new HashMap<String, Object>();
        parameters.put("group", Constant.COURSE_TYPE);
        parameters.put("ready", Constant.SCHEDULE_STATUS_READY);
        parameters.put("expire", Constant.SCHEDULE_STATUS_EXPIRE);
        parameters.put("today", now);
        
        logger.info("Start action now [{}]",now);
        
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
		Date hour = new Date();
		String occur_hour = sdf.format(hour);
		String thisMonth = DateFormatUtils.format(hour, "yyyy-MM");

        parameters.put("hour", occur_hour);
        //四月二十一日以前逾期的不算（根据活动开始时间为准）
        List<Long> studentIds = genericJdbcSupport.queryForSingleColumnList("SELECT student_id "+
                                                                            "FROM course_schedule  "+
        		                                                            "WHERE course_type != :group  "+
                                                                            "AND occur_date = :today "+
        		                                                            "AND schedule_status = :ready and is_disabled = 0 "+
        		                                                            "AND course_round_id in (SELECT id FROM course_round WHERE create_time>'2019-04-21')", parameters, Long.class);
        logger.info("... action hour [{}] studentIds [{}]",occur_hour,studentIds);
        for(Long studentId : studentIds) {       	
        	
        	Map<String, Object> params = new HashMap<String, Object>();
        	params.put("studentId", studentId);
        	params.put("month", thisMonth);
        	List<Long> ids = genericJdbcSupport.queryForSingleColumnList("SELECT id FROM user_month_count WHERE student_id = :studentId AND every_month= :month",params,Long.class);
        	if(ids.isEmpty()) {
        		logger.info("studentId [{}] thisMonth [{}]",params.get("studentId"),params.get("month"));
        		genericJdbcSupport.executeSQL("INSERT INTO user_month_count (student_id,expire_times,cancel_times,every_month) VALUES(:studentId,1,0,:month)", params);
        		
        	}else {
   
               	   genericJdbcSupport.executeSQL("UPDATE user_month_count set expire_times=expire_times+1 WHERE student_id = :studentId ", params);
               	  
            	  }
        	
        		
        	}
        
         
        	     	
    }

}
